if (!dojo._hasResource["dojo._base.fx"]) { //_hasResource checks added by build. Do not use _hasResource directly in your code.
    dojo._hasResource["dojo._base.fx"] = true;
    dojo.provide("dojo._base.fx");
    dojo.require("dojo._base.Color");
    dojo.require("dojo._base.connect");
    dojo.require("dojo._base.declare");
    dojo.require("dojo._base.lang");
    dojo.require("dojo._base.html");

    /*
     Animation losely package based on Dan Pupius' work, contributed under CLA:
     http://pupius.co.uk/js/Toolkit.Drawing.js
     */
    (function() {

        var d = dojo;

        dojo._Line = function(/*int*/ start, /*int*/ end) {
            //	summary:
            //		dojo._Line is the object used to generate values from a start value
            //		to an end value
            //	start: int
            //		Beginning value for range
            //	end: int
            //		Ending value for range
            this.start = start;
            this.end = end;
            this.getValue = function(/*float*/ n) {
                //	summary: returns the point on the line
                //	n: a floating point number greater than 0 and less than 1
                return ((this.end - this.start) * n) + this.start; // Decimal
            }
        }

        d.declare("dojo._Animation", null, {
            //	summary
            //		A generic animation class that fires callbacks into its handlers
            //		object at various states. Nearly all dojo animation functions
            //		return an instance of this method, usually without calling the
            //		.play() method beforehand. Therefore, you will likely need to
            //		call .play() on instances of dojo._Animation when one is
            //		returned.
            constructor: function(/*Object*/ args) {
                d.mixin(this, args);
                if (d.isArray(this.curve)) {
                    /* curve: Array
                     pId: a */
                    this.curve = new d._Line(this.curve[0], this.curve[1]);
                }
            },

            // duration: Integer
            //	The time in milliseonds the animation will take to run
            duration: 350,

            /*=====
             // curve: dojo._Line||Array
             //	A two element array of start and end values, or a dojo._Line instance to be
             //	used in the Animation.
             curve: null,

             // easing: Function
             //	A Function to adjust the acceleration (or deceleration) of the progress
             //	across a dojo._Line
             easing: null,
             =====*/

            // repeat: Integer
            //	The number of times to loop the animation
            repeat: 0,

            // rate: Integer
            //	the time in milliseconds to wait before advancing to next frame
            //	(used as a fps timer: rate/1000 = fps)
            rate: 10 /* 100 fps */,

            /*=====
             // delay: Integer
             // 	The time in milliseconds to wait before starting animation after it has been .play()'ed
             delay: null,

             // events
             //
             // beforeBegin: Event
             //	Synthetic event fired before a dojo._Animation begins playing (synchronous)
             beforeBegin: null,

             // onBegin: Event
             //	Synthetic event fired as a dojo._Animation begins playing (useful?)
             onBegin: null,

             // onAnimate: Event
             //	Synthetic event fired at each interval of a dojo._Animation
             onAnimate: null,

             // onEnd: Event
             //	Synthetic event fired after the final frame of a dojo._Animation
             onEnd: null,

             // onPlay: Event
             //	Synthetic event fired any time a dojo._Animation is play()'ed
             onPlay: null,

             // onPause: Event
             //	Synthetic event fired when a dojo._Animation is paused
             onPause: null,

             // onStop: Event
             //	Synthetic event fires when a dojo._Animation is stopped
             onStop: null,

             =====*/

            _percent: 0,
            _startRepeatCount: 0,

            _fire: function(/*Event*/ evt, /*Array?*/ args) {
                //	summary:
                //		Convenience function.  Fire event "evt" and pass it the
                //		arguments specified in "args".
                //	evt:
                //		The event to fire.
                //	args:
                //		The arguments to pass to the event.
                try {
                    if (this[evt]) {
                        this[evt].apply(this, args || []);
                    }
                } catch(e) {
                    // squelch and log because we shouldn't allow exceptions in
                    // synthetic event handlers to cause the internal timer to run
                    // amuck, potentially pegging the CPU. I'm not a fan of this
                    // squelch, but hopefully logging will make it clear what's
                    // going on
                    console.error("exception in animation handler for:", evt);
                    console.error(e);
                }
                return this; // dojo._Animation
            },

            play: function(/*int?*/ delay, /*Boolean?*/ gotoStart) {
                // summary:
                //		Start the animation.
                // delay:
                //		How many milliseconds to delay before starting.
                // gotoStart:
                //		If true, starts the animation from the beginning; otherwise,
                //		starts it from its current position.
                var _t = this;
                if (gotoStart) {
                    _t._stopTimer();
                    _t._active = _t._paused = false;
                    _t._percent = 0;
                } else if (_t._active && !_t._paused) {
                    return _t; // dojo._Animation
                }

                _t._fire("beforeBegin");

                var de = delay || _t.delay;
                var _p = dojo.hitch(_t, "_play", gotoStart);
                if (de > 0) {
                    setTimeout(_p, de);
                    return _t; // dojo._Animation
                }
                _p();
                return _t;
            },

            _play: function(gotoStart) {
                var _t = this;
                _t._startTime = new Date().valueOf();
                if (_t._paused) {
                    _t._startTime -= _t.duration * _t._percent;
                }
                _t._endTime = _t._startTime + _t.duration;

                _t._active = true;
                _t._paused = false;

                var value = _t.curve.getValue(_t._percent);
                if (!_t._percent) {
                    if (!_t._startRepeatCount) {
                        _t._startRepeatCount = _t.repeat;
                    }
                    _t._fire("onBegin", [value]);
                }

                _t._fire("onPlay", [value]);

                _t._cycle();
                return _t; // dojo._Animation
            },

            pause: function() {
                // summary: Pauses a running animation.
                this._stopTimer();
                if (!this._active) {
                    return this;
                    /*dojo._Animation*/
                }
                this._paused = true;
                this._fire("onPause", [this.curve.getValue(this._percent)]);
                return this; // dojo._Animation
            },

            gotoPercent: function(/*Decimal*/ percent, /*Boolean?*/ andPlay) {
                //	summary:
                //		Sets the progress of the animation.
                //	percent:
                //		A percentage in decimal notation (between and including 0.0 and 1.0).
                //	andPlay:
                //		If true, play the animation after setting the progress.
                this._stopTimer();
                this._active = this._paused = true;
                this._percent = percent;
                if (andPlay) {
                    this.play();
                }
                return this; // dojo._Animation
            },

            stop: function(/*boolean?*/ gotoEnd) {
                // summary: Stops a running animation.
                // gotoEnd: If true, the animation will end.
                if (!this._timer) {
                    return this;
                    /* dojo._Animation */
                }
                this._stopTimer();
                if (gotoEnd) {
                    this._percent = 1;
                }
                this._fire("onStop", [this.curve.getValue(this._percent)]);
                this._active = this._paused = false;
                return this; // dojo._Animation
            },

            status: function() {
                // summary: Returns a string token representation of the status of
                //			the animation, one of: "paused", "playing", "stopped"
                if (this._active) {
                    return this._paused ? "paused" : "playing"; // String
                }
                return "stopped"; // String
            },

            _cycle: function() {
                var _t = this;
                if (_t._active) {
                    var curr = new Date().valueOf();
                    var step = (curr - _t._startTime) / (_t._endTime - _t._startTime);

                    if (step >= 1) {
                        step = 1;
                    }
                    _t._percent = step;

                    // Perform easing
                    if (_t.easing) {
                        step = _t.easing(step);
                    }

                    _t._fire("onAnimate", [_t.curve.getValue(step)]);

                    if (_t._percent < 1) {
                        _t._startTimer();
                    } else {
                        _t._active = false;

                        if (_t.repeat > 0) {
                            _t.repeat--;
                            _t.play(null, true);
                        } else if (_t.repeat == -1) {
                            _t.play(null, true);
                        } else {
                            if (_t._startRepeatCount) {
                                _t.repeat = _t._startRepeatCount;
                                _t._startRepeatCount = 0;
                            }
                        }
                        _t._percent = 0;
                        _t._fire("onEnd");
                        _t._stopTimer();
                    }
                }
                return _t; // dojo._Animation
            }
        });

        var ctr = 0;
        var _globalTimerList = [];
        var runner = {
            run: function() {
            }
        };
        var timer = null;
        dojo._Animation.prototype._startTimer = function() {
            // this._timer = setTimeout(dojo.hitch(this, "_cycle"), this.rate);
            if (!this._timer) {
                this._timer = d.connect(runner, "run", this, "_cycle");
                ctr++;
            }
            if (!timer) {
                timer = setInterval(d.hitch(runner, "run"), this.rate);
            }
        };

        dojo._Animation.prototype._stopTimer = function() {
            if (this._timer) {
                d.disconnect(this._timer);
                this._timer = null;
                ctr--;
            }
            if (ctr <= 0) {
                clearInterval(timer);
                timer = null;
                ctr = 0;
            }
        };

        var _makeFadeable = (d.isIE) ? function(node) {
            // only set the zoom if the "tickle" value would be the same as the
            // default
            var ns = node.style;
            if (!ns.zoom.length && d.style(node, "zoom") == "normal") {
                // make sure the node "hasLayout"
                // NOTE: this has been tested with larger and smaller user-set text
                // sizes and works fine
                ns.zoom = "1";
                // node.style.zoom = "normal";
            }
            // don't set the width to auto if it didn't already cascade that way.
            // We don't want to f anyones designs
            if (!ns.width.length && d.style(node, "width") == "auto") {
                ns.width = "auto";
            }
        } : function() {
        };

        dojo._fade = function(/*Object*/ args) {
            //	summary:
            //		Returns an animation that will fade the node defined by
            //		args.node from the start to end values passed (args.start
            //		args.end) (end is mandatory, start is optional)

            args.node = d.byId(args.node);
            var fArgs = d.mixin({ properties: {} }, args);
            var props = (fArgs.properties.opacity = {});
            props.start = !("start" in fArgs) ?
                          function() {
                              return Number(d.style(fArgs.node, "opacity"));
                          } : fArgs.start;
            props.end = fArgs.end;

            var anim = d.animateProperty(fArgs);
            d.connect(anim, "beforeBegin", d.partial(_makeFadeable, fArgs.node));

            return anim; // dojo._Animation
        }

        /*=====
         dojo.__FadeArgs = function(node, duration, easing){
         // 	node: DOMNode|String
         //		The node referenced in the animation
         //	duration: Integer?
         //		Duration of the animation in milliseconds.
         //	easing: Function?
         //		An easing function.
         this.node = node;
         this.duration = duration;
         this.easing = easing;
         }
         =====*/

        dojo.fadeIn = function(/*dojo.__FadeArgs*/ args) {
            // summary:
            //		Returns an animation that will fade node defined in 'args' from
            //		its current opacity to fully opaque.
            return d._fade(d.mixin({ end: 1 }, args)); // dojo._Animation
        }

        dojo.fadeOut = function(/*dojo.__FadeArgs*/  args) {
            // summary:
            //		Returns an animation that will fade node defined in 'args'
            //		from its current opacity to fully transparent.
            return d._fade(d.mixin({ end: 0 }, args)); // dojo._Animation
        }

        dojo._defaultEasing = function(/*Decimal?*/ n) {
            // summary: The default easing function for dojo._Animation(s)
            return 0.5 + ((Math.sin((n + 1.5) * Math.PI)) / 2);
        }

        var PropLine = function(properties) {
            // PropLine is an internal class which is used to model the values of
            // an a group of CSS properties across an animation lifecycle. In
            // particular, the "getValue" function handles getting interpolated
            // values between start and end for a particular CSS value.
            this._properties = properties;
            for (var p in properties) {
                var prop = properties[p];
                if (prop.start instanceof d.Color) {
                    // create a reusable temp color object to keep intermediate results
                    prop.tempColor = new d.Color();
                }
            }
            this.getValue = function(r) {
                var ret = {};
                for (var p in this._properties) {
                    var prop = this._properties[p];
                    var start = prop.start;
                    if (start instanceof d.Color) {
                        ret[p] = d.blendColors(start, prop.end, r, prop.tempColor).toCss();
                    } else if (!d.isArray(start)) {
                        ret[p] = ((prop.end - start) * r) + start +
                                 (p != "opacity" ? prop.units || "px" : "");
                    }
                }
                return ret;
            }
        }

        /*=====
         dojo.declare("dojo.__AnimArgs", [dojo.__FadeArgs], {
         // Properties: Object?
         //	A hash map of style properties to Objects describing the transition,
         //	such as the properties of dojo._Line with an additional 'unit' property
         properties: {}

         //TODOC: add event callbacks
         });
         =====*/

        dojo.animateProperty = function(/*dojo.__AnimArgs*/ args) {
            //	summary:
            //		Returns an animation that will transition the properties of
            //		node defined in 'args' depending how they are defined in
            //		'args.properties'
            //
            // description:
            //		dojo.animateProperty is the foundation of most dojo.fx
            //		animations. It takes an object of "properties" corresponding to
            //		style properties, and animates them in parallel over a set
            //		duration.
            //
            // 	example:
            //		A simple animation that changes the width of the specified node.
            //	|	dojo.animateProperty({
            //	|		node: "nodeId",
            //	|		properties: { width: 400 },
            //	|	}).play();
            //		Dojo figures out the start value for the width and converts the
            //		integer specified for the width to the more expressive but
            //		verbose form `{ width: { end: '400', units: 'px' } }` which you
            //		can also specify directly
            // 	example:
            //		animate width, height, and padding over 2 seconds...the
            //		pedantic way:
            //	|	dojo.animateProperty({ node: node, duration:2000,
            //	|		properties: {
            //	|			width: { start: '200', end: '400', unit:"px" },
            //	|			height: { start:'200', end: '400', unit:"px" },
            //	|			paddingTop: { start:'5', end:'50', unit:"px" }
            //	|		}
            //	|	}).play();
            //
            // 	example:
            //		plug in a different easing function and register a callback for
            //		when the animation ends. Easing functions accept values between
            //		zero and one and return a value on that basis. In this case, an
            //		exponential-in curve.
            //	|	dojo.animateProperty({
            //	|		node: "nodeId",
            //	|		// dojo figures out the start value
            //	|		properties: { width: { end: 400 } },
            //	|		easing: function(n){
            //	|			return (n==0) ? 0 : Math.pow(2, 10 * (n - 1));
            //	|		},
            //	|		onEnd: function(){
            //	|			// called when the animation finishes
            //	|		}
            //	|	}).play(500); // delay playing half a second

            args.node = d.byId(args.node);
            if (!args.easing) {
                args.easing = d._defaultEasing;
            }

            var anim = new d._Animation(args);
            d.connect(anim, "beforeBegin", anim, function() {
                var pm = {};
                for (var p in this.properties) {
                    // Make shallow copy of properties into pm because we overwrite
                    // some values below. In particular if start/end are functions
                    // we don't want to overwrite them or the functions won't be
                    // called if the animation is reused.
                    if (p == "width" || p == "height") {
                        this.node.display = "block";
                    }
                    var prop = this.properties[p];
                    prop = pm[p] = d.mixin({}, (d.isObject(prop) ? prop : { end: prop }));

                    if (d.isFunction(prop.start)) {
                        prop.start = prop.start();
                    }
                    if (d.isFunction(prop.end)) {
                        prop.end = prop.end();
                    }
                    var isColor = (p.toLowerCase().indexOf("color") >= 0);
                    function getStyle(node, p) {
                        // dojo.style(node, "height") can return "auto" or "" on IE; this is more reliable:
                        var v = ({height: node.offsetHeight, width: node.offsetWidth})[p];
                        if (v !== undefined) {
                            return v;
                        }
                        v = d.style(node, p);
                        return (p == "opacity") ? Number(v) : (isColor ? v : parseFloat(v));
                    }
                    if (!("end" in prop)) {
                        prop.end = getStyle(this.node, p);
                    } else if (!("start" in prop)) {
                        prop.start = getStyle(this.node, p);
                    }

                    if (isColor) {
                        prop.start = new d.Color(prop.start);
                        prop.end = new d.Color(prop.end);
                    } else {
                        prop.start = (p == "opacity") ? Number(prop.start) : parseFloat(prop.start);
                    }
                }
                this.curve = new PropLine(pm);
            });
            d.connect(anim, "onAnimate", anim, function(propValues) {
                // try{
                for (var s in propValues) {
                    d.style(this.node, s, propValues[s]);
                    // this.node.style[s] = propValues[s];
                }
            });
            return anim; // dojo._Animation
        }

        dojo.anim = function(/*DOMNode|String*/     node,
            /*Object*/             properties,
            /*Integer?*/        duration,
            /*Function?*/        easing,
            /*Function?*/        onEnd,
            /*Integer?*/        delay) {
            //	summary:
            //		A simpler interface to `dojo.animateProperty()`, also returns
            //		an instance of `dojo._Animation` but begins the animation
            //		immediately, unlike nearly every other Dojo animation API.
            //	description:
            //		`dojo.anim` is a simpler (but somewhat less powerful) version
            //		of `dojo.animateProperty`.  It uses defaults for many basic properties
            //		and allows for positional parameters to be used in place of the
            //		packed "property bag" which is used for other Dojo animation
            //		methods.
            //
            //		The `dojo._Animation` object returned from `dojo.anim` will be
            //		already playing when it is returned from this function, so
            //		calling play() on it again is (usually) a no-op.
            //	node:
            //		a DOM node or the id of a node to animate CSS properties on
            //	duration:
            //		The number of milliseconds over which the animation
            //		should run. Defaults to the global animation default duration
            //		(350ms).
            //	easing:
            //		An easing function over which to calculate acceleration
            //		and deceleration of the animation through its duration.
            //		A default easing algorithm is provided, but you may
            //		plug in any you wish. A large selection of easing algorithms
            //		are available in `dojox.fx.easing`.
            //	onEnd:
            //		A function to be called when the animation finishes
            //		running.
            //	delay:
            //		The number of milliseconds to delay beginning the
            //		animation by. The default is 0.
            //	example:
            //		Fade out a node
            //	|	dojo.anim("id", { opacity: 0 });
            //	example:
            //		Fade out a node over a full second
            //	|	dojo.anim("id", { opacity: 0 }, 1000);
            return d.animateProperty({
                node: node,
                duration: duration || d._Animation.prototype.duration,
                properties: properties,
                easing: easing,
                onEnd: onEnd
            }).play(delay || 0);
        }
    })();

}
